home *** CD-ROM | disk | FTP | other *** search
/ The Fatted Calf / The Fatted Calf.iso / Unix / Shells / zsh / Source / src / lex.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-04-07  |  17.9 KB  |  959 lines

  1. /*
  2.  *
  3.  * lex.c - lexical analysis
  4.  *
  5.  * This file is part of zsh, the Z shell.
  6.  *
  7.  * This software is Copyright 1992 by Paul Falstad
  8.  *
  9.  * Permission is hereby granted to copy, reproduce, redistribute or otherwise
  10.  * use this software as long as: there is no monetary profit gained
  11.  * specifically from the use or reproduction of this software, it is not
  12.  * sold, rented, traded or otherwise marketed, and this copyright notice is
  13.  * included prominently in any copy made.
  14.  *
  15.  * The author make no claims as to the fitness or correctness of this software
  16.  * for any use whatsoever, and it is provided as is. Any use of this software
  17.  * is at the user's own risk.
  18.  *
  19.  */
  20.  
  21. #include "zsh.h"
  22.  
  23. /* lexical state */
  24.  
  25. static int dbparens, in_brace_param = 0;
  26.  
  27. struct lexstack {
  28.     struct lexstack *next;
  29.  
  30.     int incmdpos;
  31.     int incond;
  32.     int incasepat;
  33.     int dbparens;
  34.     int in_brace_param;
  35.     int alstat;
  36.     char *hlastw;
  37.     int isfirstln;
  38.     int isfirstch;
  39.     int histremmed;
  40.     int histdone;
  41.     int spaceflag;
  42.     int stophist;
  43.     int lithist;
  44.     int alstackind;
  45.     int hlinesz;
  46.     char *hline;
  47.     char *hptr;
  48.  
  49.     unsigned char *cstack;
  50.     int csp;
  51. };
  52.  
  53. static struct lexstack *lstack = NULL;
  54.  
  55. /* save the lexical state */
  56.  
  57. /* is this a hack or what? */
  58.  
  59. void lexsave()
  60. {                /**/
  61.     struct lexstack *ls;
  62.  
  63.     ls = (struct lexstack *)malloc(sizeof(struct lexstack));
  64.  
  65.     ls->incmdpos = incmdpos;
  66.     ls->incond = incond;
  67.     ls->incasepat = incasepat;
  68.     ls->dbparens = dbparens;
  69.     ls->in_brace_param = in_brace_param;
  70.     ls->alstat = alstat;
  71.     ls->alstackind = alstackind;
  72.     ls->isfirstln = isfirstln;
  73.     ls->isfirstch = isfirstch;
  74.     ls->histremmed = histremmed;
  75.     ls->histdone = histdone;
  76.     ls->spaceflag = spaceflag;
  77.     ls->stophist = stophist;
  78.     ls->lithist = lithist;
  79.     ls->hline = chline;
  80.     ls->hptr = hptr;
  81.     ls->hlastw = hlastw;
  82.     ls->hlinesz = hlinesz;
  83.     ls->cstack = cmdstack;
  84.     ls->csp = cmdsp;
  85.     cmdstack = (unsigned char *)zalloc(256);
  86.     in_brace_param = 0;
  87.     cmdsp = 0;
  88.     inredir = 0;
  89.  
  90.     ls->next = lstack;
  91.     lstack = ls;
  92. }
  93.  
  94. /* restore lexical state */
  95.  
  96. void lexrestore()
  97. {                /**/
  98.     struct lexstack *ln;
  99.  
  100.     if (!lstack) {
  101.     zerr("lexrestore without lexsave", NULL, 0);
  102.     return;
  103.     }
  104.     incmdpos = lstack->incmdpos;
  105.     incond = lstack->incond;
  106.     incasepat = lstack->incasepat;
  107.     dbparens = lstack->dbparens;
  108.     in_brace_param = lstack->in_brace_param;
  109.     alstat = lstack->alstat;
  110.     isfirstln = lstack->isfirstln;
  111.     isfirstch = lstack->isfirstch;
  112.     histremmed = lstack->histremmed;
  113.     histdone = lstack->histdone;
  114.     spaceflag = lstack->spaceflag;
  115.     stophist = lstack->stophist;
  116.     lithist = lstack->lithist;
  117.     chline = lstack->hline;
  118.     hptr = lstack->hptr;
  119.     hlastw = lstack->hlastw;
  120.     if (cmdstack)
  121.     free(cmdstack);
  122.     cmdstack = lstack->cstack;
  123.     cmdsp = lstack->csp;
  124.     clearalstack();
  125.     alstackind = lstack->alstackind;
  126.     hlinesz = lstack->hlinesz;
  127.     lexstop = errflag = 0;
  128.  
  129.     ln = lstack->next;
  130.     free(lstack);
  131.     lstack = ln;
  132. }
  133.  
  134. void yylex()
  135. {                /**/
  136.     if (tok == LEXERR)
  137.     return;
  138.     do
  139.     tok = gettok();
  140.     while (tok != ENDINPUT && exalias());
  141.     if (tok != NEWLIN)
  142.     isnewlin = 0;
  143.     else
  144.     isnewlin = (inbufct) ? -1 : 1;
  145.     if (tok == SEMI || tok == NEWLIN)
  146.     tok = SEPER;
  147. }
  148.  
  149. void ctxtlex()
  150. {                /**/
  151.     static int oldpos;
  152.  
  153.     yylex();
  154.     switch (tok) {
  155.     case SEPER:
  156.     case NEWLIN:
  157.     case SEMI:
  158.     case DSEMI:
  159.     case AMPER:
  160.     case INPAR:
  161.     case INBRACE:
  162.     case DBAR:
  163.     case DAMPER:
  164.     case BAR:
  165.     case BARAMP:
  166.     case INOUTPAR:
  167.     case DO:
  168.     case THEN:
  169.     case ELIF:
  170.     case ELSE:
  171.     incmdpos = 1;
  172.     break;
  173.     case STRING:        /* case ENVSTRING: */
  174.     case ENVARRAY:
  175.     case OUTPAR:
  176.     case CASE:
  177.     incmdpos = 0;
  178.     break;
  179.     }
  180.     if (IS_REDIROP(tok) || tok == FOR || tok == FOREACH || tok == SELECT) {
  181.     inredir = 1;
  182.     oldpos = incmdpos;
  183.     incmdpos = 0;
  184.     } else if (inredir) {
  185.     incmdpos = oldpos;
  186.     inredir = 0;
  187.     }
  188. }
  189.  
  190. #define LX1_BKSLASH 0
  191. #define LX1_COMMENT 1
  192. #define LX1_NEWLIN 2
  193. #define LX1_SEMI 3
  194. #define LX1_BANG 4
  195. #define LX1_AMPER 5
  196. #define LX1_BAR 6
  197. #define LX1_INPAR 7
  198. #define LX1_OUTPAR 8
  199. #define LX1_INBRACE 9
  200. #define LX1_OUTBRACE 10
  201. #define LX1_INBRACK 11
  202. #define LX1_OUTBRACK 12
  203. #define LX1_INANG 13
  204. #define LX1_OUTANG 14
  205. #define LX1_OTHER 15
  206.  
  207. #define LX2_BREAK 0
  208. #define LX2_OUTPAR 1
  209. #define LX2_BAR 2
  210. #define LX2_STRING 3
  211. #define LX2_INBRACK 4
  212. #define LX2_OUTBRACK 5
  213. #define LX2_TILDE 6
  214. #define LX2_INPAR 7
  215. #define LX2_INBRACE 8
  216. #define LX2_OUTBRACE 9
  217. #define LX2_OUTANG 10
  218. #define LX2_INANG 11
  219. #define LX2_EQUALS 12
  220. #define LX2_BKSLASH 13
  221. #define LX2_QUOTE 14
  222. #define LX2_DQUOTE 15
  223. #define LX2_BQUOTE 16
  224. #define LX2_OTHER 17
  225.  
  226. unsigned char lexact1[256], lexact2[256], lextok2[256];
  227.  
  228. void initlextabs()
  229. {                /**/
  230.     int t0;
  231.     static char *lx1 = "\\q\n;!&|(){}[]<>xx";
  232.     static char *lx2 = "x)|$[]~({}><=\\\'\"`x";
  233.  
  234.     for (t0 = 0; t0 != 256; t0++) {
  235.     lexact1[t0] = LX1_OTHER;
  236.     lexact2[t0] = LX2_OTHER;
  237.     lextok2[t0] = t0;
  238.     }
  239.     for (t0 = 0; lx1[t0]; t0++)
  240.     if (lx1[t0] != 'x')
  241.         lexact1[(int)lx1[t0]] = t0;
  242.     for (t0 = 0; lx2[t0]; t0++)
  243.     if (lx2[t0] != 'x')
  244.         lexact2[(int)lx2[t0]] = t0;
  245.     lexact2[';'] = LX2_BREAK;
  246.     lexact2['&'] = LX2_BREAK;
  247.     lextok2[','] = Comma;
  248.     lextok2['*'] = Star;
  249.     lextok2['?'] = Quest;
  250.     lextok2['{'] = Inbrace;
  251.     lextok2['['] = Inbrack;
  252.     lextok2['$'] = String;
  253. }
  254.  
  255. /* initialize lexical state */
  256.  
  257. void lexinit()
  258. {                /**/
  259.     incond = incasepat = nocorrect =
  260.     dbparens = alstat = lexstop = in_brace_param = 0;
  261.     incmdpos = 1;
  262.     tok = ENDINPUT;
  263.     if (isset(EXTENDEDGLOB)) {
  264.     lextok2['#'] = Pound;
  265.     lextok2['^'] = Hat;
  266.     } else {
  267.     lextok2['#'] = '#';
  268.     lextok2['^'] = '^';
  269.     }
  270. }
  271.  
  272. int len = 0, bsiz = 256;
  273. char *bptr;
  274.  
  275. /* add a char to the string buffer */
  276.  
  277. void add(c)            /**/
  278. int c;
  279. {
  280.     *bptr++ = c;
  281.     if (bsiz == ++len) {
  282.     int newbsiz;
  283.  
  284.     newbsiz = bsiz * 8;
  285.     while (newbsiz < inbufct)
  286.         newbsiz *= 2;
  287.     bptr = len + (tokstr = (char *)hrealloc(tokstr, bsiz, newbsiz));
  288.     bsiz = newbsiz;
  289.     }
  290. }
  291.  
  292. SPROTO(void unadd, (void));
  293.  
  294. static void unadd()
  295. {
  296.     bptr--;
  297.     len--;
  298. }
  299.  
  300. int gettok()
  301. {                /**/
  302.     int bct = 0, pct = 0, brct = 0;
  303.     int c, d, intpos = 1;
  304.     int peekfd = -1, peek, ninbracks;
  305.  
  306.   beginning:
  307.     hlastw = NULL;
  308.     tokstr = NULL;
  309.     parbegin = -1;
  310.     while (iblank(c = hgetc()) && !lexstop);
  311.     isfirstln = 0;
  312.     wordbeg = inbufct;
  313.     hwbegin();
  314.     hwaddc(c);
  315.     if (dbparens) {
  316.     hungetc(c);
  317.     c = '\"';
  318.     } else if (idigit(c)) {    /* handle 1< foo */
  319.     d = hgetc();
  320.     hungetc(d);
  321.     lexstop = 0;
  322.     if (d == '>' || d == '<') {
  323.         peekfd = c - '0';
  324.         c = hgetc();
  325.     }
  326.     }
  327. /* chars in initial position in word */
  328.  
  329.     if (c == hashchar &&
  330.     (isset(INTERACTIVECOMMENTS) ||
  331.      (!zleparse && (!interact || unset(SHINSTDIN) || strin))))
  332.     {
  333.         /* History is handled here to prevent extra newlines
  334.          * being inserted into the history.
  335.          *
  336.          * Also ignore trailing spaces to prevent history from
  337.          * changing. If trailing spaces are not ignored then
  338.          * each time a comment inside a command (a 'for' loop
  339.          * is a good example) is seen an extra space is appended
  340.          * to the end of the comment causing a new history entry
  341.          * even if HISTIGNOREDUPS is set.
  342.          */
  343.     int nsp = 0;        /* number of contiguos spaces */
  344.  
  345.     while ((c = hgetch()) != '\n' && !lexstop) {
  346.         if (c == ' ')
  347.         ++nsp;
  348.         else {
  349.         while (nsp) {
  350.             hwaddc(' ');
  351.             --nsp;
  352.         }
  353.         hwaddc(c);
  354.         }
  355.     }
  356.     if (errflag)
  357.         peek = LEXERR;
  358.     else {
  359.         hwadd();
  360.         hwbegin();
  361.         hwaddc('\n');
  362.         peek = NEWLIN;
  363.     }
  364.     return peek;
  365.     }
  366.     if (lexstop)
  367.     return (errflag) ? LEXERR : ENDINPUT;
  368.     switch (lexact1[(unsigned char)c]) {
  369.     case LX1_BKSLASH:
  370.     d = hgetc();
  371.     if (d == '\n')
  372.         goto beginning;
  373.     hungetc(d);
  374.     break;
  375.     case LX1_NEWLIN:
  376.     return NEWLIN;
  377.     case LX1_SEMI:
  378.     d = hgetc();
  379.     if (d != ';') {
  380.         hungetc(d);
  381.         return SEMI;
  382.     }
  383.     return DSEMI;
  384.     case LX1_BANG:
  385.     d = hgetc();
  386.     hungetc(d);
  387.     if (!inblank(d))
  388.         break;
  389.     if (incmdpos || incond)
  390.         return BANG;
  391.     break;
  392.     case LX1_AMPER:
  393.     d = hgetc();
  394.     if (d != '&') {
  395.         hungetc(d);
  396.         return AMPER;
  397.     }
  398.     return DAMPER;
  399.     case LX1_BAR:
  400.     d = hgetc();
  401.     if (d == '|')
  402.         return DBAR;
  403.     else if (d == '&')
  404.         return BARAMP;
  405.     hungetc(d);
  406.     return BAR;
  407.     case LX1_INPAR:
  408.     d = hgetc();
  409.     if (d == '(' && incmdpos) {
  410.         dbparens = 1;
  411.         return DINPAR;
  412.     } else if (d == ')')
  413.         return INOUTPAR;
  414.     hungetc(d);
  415.     if (!(incond == 1 || incmdpos))
  416.         break;
  417.     return INPAR;
  418.     case LX1_OUTPAR:
  419.     return OUTPAR;
  420.     case LX1_INBRACE:
  421.     if (!incmdpos)
  422.         break;
  423.     return INBRACE;
  424.     case LX1_OUTBRACE:
  425.     return OUTBRACE;
  426.     case LX1_INBRACK:
  427.     if (!incmdpos)
  428.         break;
  429.     d = hgetc();
  430.     if (d == '[')
  431.         return DINBRACK;
  432.     hungetc(d);
  433.     break;
  434.     case LX1_OUTBRACK:
  435.     if (!incond)
  436.         break;
  437.     d = hgetc();
  438.     if (d == ']')
  439.         return DOUTBRACK;
  440.     hungetc(d);
  441.     break;
  442.     case LX1_INANG:
  443.     d = hgetc();
  444.     if ((!incmdpos && d == '(') || incasepat) {
  445.         hungetc(d);
  446.         break;
  447.     } else if (idigit(d) || d == '-' || d == '>') {
  448.         int tbs = 256, n = 0, nc;
  449.         char *tbuf, *tbp, *ntb;
  450.  
  451.         tbuf = tbp = (char *) zalloc(tbs);
  452.         hungetc(d);
  453.  
  454.         while ((nc = hgetc()) && !lexstop) {
  455.         if (!idigit(nc) && nc != '-')
  456.             break;
  457.         *tbp++ = (char) nc;
  458.         if (++n == tbs) {
  459.             ntb = (char *) realloc(tbuf, tbs *= 2);
  460.             tbp += ntb - tbuf;
  461.             tbuf = ntb;
  462.         }
  463.         }
  464.         if (nc == '>' && !lexstop) {
  465.         lexstop = 0;
  466.         hungetc(nc);
  467.         while (n--)
  468.             hungetc(*--tbp);
  469.         zfree(tbuf, tbs);
  470.         break;
  471.         }
  472.         lexstop = 0;
  473.         if (nc)
  474.         hungetc(nc);
  475.         while (n--)
  476.         hungetc(*--tbp);
  477.         zfree(tbuf, tbs);
  478.         peek = INANG;
  479.     } else if (d == '<') {
  480.         int e = hgetc();
  481.  
  482.         if (e == '(') {
  483.         hungetc(e);
  484.         hungetc(d);
  485.         peek = INANG;
  486.         } else if (e == '<')
  487.         peek = TRINANG;
  488.         else if (e == '-')
  489.         peek = DINANGDASH;
  490.         else {
  491.         hungetc(e);
  492.         peek = DINANG;
  493.         }
  494.     } else if (d == '&')
  495.         peek = INANGAMP;
  496.     else {
  497.         peek = INANG;
  498.         hungetc(d);
  499.     }
  500.     tokfd = peekfd;
  501.     return peek;
  502.     case LX1_OUTANG:
  503.     d = hgetc();
  504.     if (d == '(') {
  505.         hungetc(d);
  506.         break;
  507.     } else if (d == '&') {
  508.         d = hgetc();
  509.         if (d == '!')
  510.         peek = OUTANGAMPBANG;
  511.         else {
  512.         hungetc(d);
  513.         peek = OUTANGAMP;
  514.         }
  515.     } else if (d == '!')
  516.         peek = OUTANGBANG;
  517.     else if (d == '>') {
  518.         d = hgetc();
  519.         if (d == '&') {
  520.         d = hgetc();
  521.         if (d == '!')
  522.             peek = DOUTANGAMPBANG;
  523.         else {
  524.             hungetc(d);
  525.             peek = DOUTANGAMP;
  526.         }
  527.         } else if (d == '!')
  528.         peek = DOUTANGBANG;
  529.         else if (d == '(') {
  530.         hungetc(d);
  531.         hungetc('>');
  532.         peek = OUTANG;
  533.         } else {
  534.         hungetc(d);
  535.         peek = DOUTANG;
  536.         if (isset(NOCLOBBER))
  537.             hwaddc('!');
  538.         }
  539.     } else {
  540.         hungetc(d);
  541.         peek = OUTANG;
  542.         if (!incond && isset(NOCLOBBER))
  543.         hwaddc('!');
  544.     }
  545.     tokfd = peekfd;
  546.     return peek;
  547.     }
  548.  
  549. /* we've started a string, now get the rest of it, performing
  550.         tokenization */
  551.  
  552.     peek = STRING;
  553.     len = 0;
  554.     bptr = tokstr = (char *)ncalloc(bsiz = 256);
  555.     for (;;) {
  556.     int act;
  557.     int e;
  558.     int endchar;
  559.  
  560.     if (inblank(c) && !bct && !pct)
  561.         act = LX2_BREAK;
  562.     else {
  563.         act = lexact2[(unsigned char)c];
  564.         c = lextok2[(unsigned char)c];
  565.     }
  566.     switch (act) {
  567.     case LX2_BREAK:
  568.         if (!in_brace_param)
  569.         goto brk;
  570.         break;
  571.     case LX2_OUTPAR:
  572.         if (!pct)
  573.         goto brk;
  574.         c = Outpar;
  575.         pct--;
  576.         break;
  577.     case LX2_BAR:
  578.         if (!pct && !incasepat)
  579.         goto brk;
  580.         c = Bar;
  581.         break;
  582.     case LX2_STRING:
  583.         e = hgetc();
  584.         if (e == '[') {
  585.         cmdpush(CS_MATHSUBST);
  586.         add(String);
  587.         add(Inbrack);
  588.         ninbracks = 1;
  589.         while (ninbracks && (c = hgetc()) && !lexstop) {
  590.             if (c == '[')
  591.             ninbracks++;
  592.             else if (c == ']')
  593.             ninbracks--;
  594.             if (ninbracks)
  595.             add(c);
  596.         }
  597.         c = Outbrack;
  598.         cmdpop();
  599.         } else if (e == '(') {
  600.         add(String);
  601.         if (skipcomm()) {
  602.             peek = LEXERR;
  603.             goto brk;
  604.         }
  605.         c = Outpar;
  606.         } else {
  607.         if (e == '{')
  608.             in_brace_param = 1;
  609.         hungetc(e);
  610.         }
  611.         break;
  612.     case LX2_INBRACK:
  613.         brct++;
  614.         break;
  615.     case LX2_OUTBRACK:
  616.         if (incond && !brct)
  617.         goto brk;
  618.         brct--;
  619.         c = Outbrack;
  620.         break;
  621.     case LX2_TILDE:    /* if (intpos) */
  622.         c = Tilde;
  623.         break;
  624.     case LX2_INPAR:
  625.         e = hgetc();
  626.         hungetc(e);
  627.         if (e == ')' ||
  628.         (incmdpos && !brct && peek != ENVSTRING))
  629.         goto brk;
  630.         pct++;
  631.         c = Inpar;
  632.         break;
  633.     case LX2_INBRACE:
  634.         bct++;
  635.         break;
  636.     case LX2_OUTBRACE:
  637.         if (!bct)
  638.         goto brk;
  639.         if (!--bct && in_brace_param)
  640.         in_brace_param = 0;
  641.         c = Outbrace;
  642.         break;
  643.     case LX2_OUTANG:
  644.         e = hgetc();
  645.         if (e != '(') {
  646.         hungetc(e);
  647.         goto brk;
  648.         }
  649.         add(Outang);
  650.         if (skipcomm()) {
  651.         peek = LEXERR;
  652.         goto brk;
  653.         }
  654.         c = Outpar;
  655.         break;
  656.     case LX2_INANG:
  657.         e = hgetc();
  658.         if (!(idigit(e) || e == '-' || e == '>' || e == '(' || e == ')')) {
  659.         hungetc(e);
  660.         goto brk;
  661.         }
  662.         c = Inang;
  663.         if (e == '(') {
  664.         add(c);
  665.         if (skipcomm()) {
  666.             peek = LEXERR;
  667.             goto brk;
  668.         }
  669.         c = Outpar;
  670.         } else if (e == ')')
  671.         hungetc(e);
  672.         else {
  673.         add(c);
  674.         c = e;
  675.         while (c != '>' && !lexstop)
  676.             add(c), c = hgetc();
  677.         c = Outang;
  678.         }
  679.         break;
  680.     case LX2_EQUALS:
  681.         if (intpos) {
  682.         e = hgetc();
  683.         if (e != '(') {
  684.             hungetc(e);
  685.             c = Equals;
  686.         } else {
  687.             add(Equals);
  688.             if (skipcomm()) {
  689.             peek = LEXERR;
  690.             goto brk;
  691.             }
  692.             c = Outpar;
  693.         }
  694.         } else if (peek != ENVSTRING && incmdpos && !bct) {
  695.         e = hgetc();
  696.         if (e == '(' && incmdpos) {
  697.             *bptr = '\0';
  698.             return ENVARRAY;
  699.         }
  700.         hungetc(e);
  701.         peek = ENVSTRING;
  702.         intpos = 2;
  703.         } else
  704.         c = Equals;
  705.         break;
  706.     case LX2_BKSLASH:
  707.         c = hgetc();
  708.         if (c == '\n') {
  709.         c = hgetc();
  710.         continue;
  711.         }
  712.         add(Bnull);
  713.         add(c);
  714.         c = hgetc();
  715.         continue;
  716.     case LX2_QUOTE:
  717.         add(Snull);
  718.  
  719.     /* we add the Nularg to prevent this:
  720.  
  721.                 echo $PA'TH'
  722.  
  723.                 from printing the path. */
  724.  
  725.         cmdpush(CS_QUOTE);
  726.         for (;;) {
  727.         while ((c = hgetc()) != '\'' && !lexstop) {
  728.             if (isset(CSHJUNKIEQUOTES) && c == '\n') {
  729.             if (bptr[-1] == '\\')
  730.                 unadd();
  731.             else
  732.                 break;
  733.             }
  734.             add(c);
  735.         }
  736.         if (c != '\'') {
  737.             zerr("unmatched \'", NULL, 0);
  738.             peek = LEXERR;
  739.             cmdpop();
  740.             goto brk;
  741.         }
  742.         e = hgetc();
  743.         if (e != '\'' || unset(RCQUOTES))
  744.             break;
  745.         add(c);
  746.         }
  747.         cmdpop();
  748.         hungetc(e);
  749.         c = Snull;
  750.         break;
  751.     case LX2_DQUOTE:
  752.         add(Dnull);
  753.         cmdpush(CS_DQUOTE);
  754.         endchar = dbparens ? ')' : '"';
  755.         while (((c = hgetc()) != endchar || (dbparens && pct > 0))
  756.            && !lexstop)
  757.         if (c == '\\') {
  758.             c = hgetc();
  759.             if (c != '\n') {
  760.             add(c == '$' || c == '\\' ||
  761.                 c == '\"' || c == '`' ? Bnull : '\\');
  762.             add(c);
  763.             }
  764.         } else {
  765.             if (isset(CSHJUNKIEQUOTES) && c == '\n') {
  766.             if (bptr[-1] == '\\')
  767.                 unadd();
  768.             else
  769.                 break;
  770.             }
  771.             if (c == '$') {
  772.             e = hgetc();
  773.             if (e == '(') {
  774.                 add(Qstring);
  775.                 if (skipcomm()) {
  776.                 peek = LEXERR;
  777.                 cmdpop();
  778.                 goto brk;
  779.                 }
  780.                 c = Outpar;
  781.             } else if (e == '[') {
  782.                 add(String);
  783.                 add(Inbrack);
  784.                 while ((c = hgetc()) != ']' && !lexstop)
  785.                 add(c);
  786.                 c = Outbrack;
  787.             } else {
  788.                 c = Qstring;
  789.                 hungetc(e);
  790.             }
  791.             } else if (c == '`')
  792.             c = Qtick;
  793.             else if (dbparens) {
  794.             if (c == '(')
  795.                 pct++;
  796.             else if (c == ')')
  797.                 pct--;
  798.             else if (c == '\n')
  799.                 break;
  800.             }
  801.             add(c);
  802.         }
  803.         cmdpop();
  804.         if (c != endchar || (dbparens && (pct || (c = hgetc()) != ')'))) {
  805.         if (!dbparens)
  806.             zerr("unmatched \"", NULL, 0);
  807.         peek = LEXERR;
  808.         goto brk;
  809.         }
  810.         if (dbparens) {
  811.         dbparens = 0;
  812.         add(Dnull);
  813.         *bptr = '\0';
  814.         return DOUTPAR;
  815.         }
  816.         c = Dnull;
  817.         break;
  818.     case LX2_BQUOTE:
  819.         add(Tick);
  820.         cmdpush(CS_BQUOTE);
  821.         parbegin = inbufct;
  822.         while ((c = hgetc()) != '`' && !lexstop)
  823.         if (c == '\\') {
  824.             c = hgetc();
  825.             if (c != '\n') {
  826.             add(c == '`' || c == '\\' || c == '$' ? Bnull : '\\');
  827.             add(c);
  828.             }
  829.         } else {
  830.             if (isset(CSHJUNKIEQUOTES) && c == '\n') {
  831.             if (bptr[-1] == '\\')
  832.                 unadd();
  833.             else
  834.                 break;
  835.             }
  836.             add(c);
  837.         }
  838.         cmdpop();
  839.         if (c != '`') {
  840.         if (!zleparse)
  841.             zerr("unmatched `", NULL, 0);
  842.         peek = LEXERR;
  843.         goto brk;
  844.         }
  845.         c = Tick;
  846.         parbegin = -1;
  847.         break;
  848.     }
  849.     add(c);
  850.     c = hgetc();
  851.     if (intpos)
  852.         intpos--;
  853.     if (lexstop)
  854.         break;
  855.     }
  856.   brk:
  857.     hungetc(c);
  858.     *bptr = '\0';
  859.     return peek;
  860. }
  861.  
  862. /* expand aliases, perhaps */
  863.  
  864. int exalias()
  865. {                /**/
  866.     struct alias *an;
  867.     char *s, *t;
  868.  
  869.     s = yytext = hwadd();
  870.     for (t = s; *t && *t != HISTSPACE; t++);
  871.     if (!*t)
  872.     t = NULL;
  873.     else
  874.     *t = '\0';
  875.     if (interact && isset(SHINSTDIN) && !strin && !incasepat && tok == STRING &&
  876.     (isset(CORRECTALL) || (isset(CORRECT) && incmdpos)) && !nocorrect)
  877.     spckword(&tokstr, &s, &t, !incmdpos, 1);
  878.     if (zleparse && !alstackind) {
  879.     int zp = zleparse;
  880.  
  881.     gotword(s);
  882.     if (zp && !zleparse) {
  883.         if (t)
  884.         *t = HISTSPACE;
  885.         return 0;
  886.     }
  887.     }
  888.     an = noaliases ? NULL : (struct alias *)gethnode(s, aliastab);
  889.     if (t)
  890.     *t = HISTSPACE;
  891.     if (alstackind != MAXAL && an && !an->inuse)
  892.     if (!(an->cmd && !incmdpos && alstat != ALSTAT_MORE)) {
  893.         if (an->cmd < 0) {
  894.         tok = DO - an->cmd - 1;
  895.         return 0;
  896.         } else {
  897.         an->inuse = 1;
  898.         hungets(ALPOPS);
  899.         hungets((alstack[alstackind++] = an)->text);
  900.         alstat = 0;
  901.         /* remove from history if it begins with space */
  902.         if (isset(HISTIGNORESPACE) && an->text[0] == ' ')
  903.             remhist();
  904.         lexstop = 0;
  905.         return 1;
  906.         }
  907.     }
  908.     return 0;
  909. }
  910.  
  911. /* skip (...) */
  912.  
  913. int skipcomm()
  914. {                /**/
  915.     int pct = 1, c;
  916.  
  917.     cmdpush(CS_CMDSUBST);
  918.     parbegin = inbufct;
  919.     c = Inpar;
  920.     do {
  921.     add(c);
  922.     c = hgetc();
  923.     if (itok(c) || lexstop)
  924.         break;
  925.     else if (c == '(')
  926.         pct++;
  927.     else if (c == ')')
  928.         pct--;
  929.     else if (c == '\\') {
  930.         add(c);
  931.         c = hgetc();
  932.     } else if (c == '\'') {
  933.         add(c);
  934.         while ((c = hgetc()) != '\'' && !lexstop)
  935.         add(c);
  936.     } else if (c == '\"') {
  937.         add(c);
  938.         while ((c = hgetc()) != '\"' && !lexstop)
  939.         if (c == '\\') {
  940.             add(c);
  941.             add(hgetc());
  942.         } else
  943.             add(c);
  944.     } else if (c == '`') {
  945.         add(c);
  946.         while ((c = hgetc()) != '`' && !lexstop)
  947.         if (c == '\\')
  948.             add(c), add(hgetc());
  949.         else
  950.             add(c);
  951.     }
  952.     }
  953.     while (pct);
  954.     if (!lexstop)
  955.     parbegin = -1;
  956.     cmdpop();
  957.     return lexstop;
  958. }
  959.